package lin.an.food.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lin.an.enums.CommonSortOrderEnum;
import lin.an.enums.StatusEnum;
import lin.an.exception.CommonException;
import lin.an.food.entity.Food;
import lin.an.food.entity.FoodClicks;
import lin.an.food.entity.FoodDetails;
import lin.an.food.mapper.FoodMapper;
import lin.an.food.param.*;
import lin.an.food.service.FoodClicksService;
import lin.an.food.service.FoodDetailsService;
import lin.an.food.service.FoodService;
import lin.an.food.vo.FoodClicksVo;
import lin.an.food.vo.FoodDetailsVo;
import lin.an.pojo.CommonPageRequest;
import lin.an.user.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import static lin.an.enums.CategoryEnum.*;

/**
 * @author zhoulinq
 * @date 2025/3/18
 */
@Service
public class FoodServiceImpl extends ServiceImpl<FoodMapper, Food> implements FoodService {

    @Autowired
    private OSS ossClient;
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Autowired
    private FoodMapper foodMapper;
    @Autowired
    private FoodClicksService foodClicksService;
    @Autowired
    private FoodDetailsService foodDetailsService;
    /**
     * 增加美食信息
     *
     */
    @Override
    public void add(FoodAddParam foodAddParam) {
        checkAddParam(foodAddParam);
        Food food = BeanUtil.toBean(foodAddParam,Food.class);
        food.setStatus(StatusEnum.ENABLE.getValue());
        this.save(food);
        // 创建美食详情
        LambdaQueryWrapper<Food> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Food::getFoodName,foodAddParam.getFoodName());
        Food food1 = this.getOne(lambdaQueryWrapper);
        FoodDetails foodDetails = new FoodDetails();
        foodDetails.setFoodId(food1.getFoodId());
        foodDetails.setFoodName(food.getFoodName());
        foodDetails.setIngredients(foodAddParam.getIngredients());
        foodDetails.setPreparation(foodAddParam.getPreparation());
        foodDetails.setReviews("暂无评价");
        foodDetails.setLikes(0);
        foodDetails.setFavorites(0);
        foodDetailsService.save(foodDetails);
    }


    /**
     * 删除美食信息（批量）
     */
    @Transactional(rollbackFor = {java.lang.Exception.class})
    @Override
    public void delete(List<FoodDeleteParam> foodDeleteParamList) {
        List<Integer> foodIdList = CollStreamUtil.toList(foodDeleteParamList,FoodDeleteParam::getFoodId);
        this.removeByIds(foodIdList);
    }

    @Transactional(rollbackFor = {java.lang.Exception.class})
    @Override
    public void edit(FoodEditParam foodEditParam) {
        Food food = this.getById(foodEditParam.getFoodId());
        if(ObjectUtil.isEmpty(food)){
            throw new CommonException("美食不存在，id值为：{}", foodEditParam.getFoodId());
        }
        BeanUtil.copyProperties(foodEditParam, food);
        this.updateById(food);
    }

    /**
     * 分页查询数据
     * @param foodPageParam
     * @return
     */
    @Override
    public Page<Food> page(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        QueryWrapper<Food> queryWrapper = new QueryWrapper<Food>().checkSqlInjection();
        if (ObjectUtil.isAllNotEmpty(foodPageParam.getSortField(), foodPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(foodPageParam.getSortOrder());
            queryWrapper.orderBy(true, foodPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(foodPageParam.getSortField()));
        }
        return this.page(page, queryWrapper);
    }

    /**
     * 检查美食增加参数
     * @param foodAddParam
     */
    private void checkAddParam(FoodAddParam foodAddParam){
        if (this.count(new LambdaQueryWrapper<Food>()
                .eq(Food::getFoodName, foodAddParam.getFoodName())) > 0) {
            throw new CommonException("存在重复美食，美食名为：{}", foodAddParam.getFoodName());
        }
    }

    @Override
    public String uploadReturnUrl(MultipartFile file) {
        if (file.isEmpty()) {
            return "上传文件为空";
        }
        try {
            // 生成唯一的文件名
            String fileName = file.getOriginalFilename();
            // 获取文件输入流
            InputStream inputStream = file.getInputStream();
            // 上传文件到 OSS
            PutObjectResult result = ossClient.putObject(bucketName, fileName, inputStream);
            // 关闭输入流
            inputStream.close();
            // 返回文件的访问 URL
            return "https://" + bucketName + "." + endpoint + "/" + fileName;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 美食推荐功能
     * @param userId 用户ID
     * @return 推荐的美食列表
     */
    @Override
    public List<Food> recommend(Integer userId) {
        // 获取用户收藏的美食ID列表
        List<Integer> favoriteFoodIds = foodMapper.getUserFavoriteFoodIds(userId);
        
        // 如果用户没有收藏美食，推荐点击率最高的前十个美食
        if (ObjectUtil.isEmpty(favoriteFoodIds)) {
            return getTopClicksFoods();
        }
        
        // 获取用户收藏的美食信息
        List<Food> favoriteFoods = this.listByIds(favoriteFoodIds);
        
        // 如果收藏的美食为空，返回点击率最高的前十个美食
        if (ObjectUtil.isEmpty(favoriteFoods)) {
            return getTopClicksFoods();
        }
        
        // 获取用户收藏的美食分类
        Set<String> favoriteCategories = favoriteFoods.stream()
                .map(Food::getCategoryName)
                .collect(Collectors.toSet());
        
        // 根据用户收藏的美食分类，推荐同类中点击率最高的前十个美食
        return getTopClicksFoodsByCategories(favoriteCategories);
    }
    
    /**
     * 获取点击率最高的前十个美食
     * @return 点击率最高的前十个美食列表
     */
    private List<Food> getTopClicksFoods() {
        // 获取点击数最多的前10条记录
        List<FoodClicksVo> topClicks = foodClicksService.getTopClicks();
        
        // 如果没有点击记录，返回空列表
        if (ObjectUtil.isEmpty(topClicks)) {
            return new ArrayList<>();
        }
        
        // 获取美食ID列表
        List<Integer> foodIds = topClicks.stream()
                .map(vo -> {
                    // 根据美食名称查询美食ID
                    LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(Food::getFoodName, vo.getFoodName());
                    Food food = this.getOne(queryWrapper);
                    return food != null ? food.getFoodId() : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        
        // 根据ID列表查询美食信息
        return this.listByIds(foodIds);
    }
    
    /**
     * 根据分类获取点击率最高的前十个美食
     * @param categories 美食分类集合
     * @return 点击率最高的前十个美食列表
     */
    private List<Food> getTopClicksFoodsByCategories(Set<String> categories) {
        // 获取点击数最多的前10条记录
        List<FoodClicksVo> topClicks = foodClicksService.getTopClicks();
        
        // 如果没有点击记录，返回空列表
        if (ObjectUtil.isEmpty(topClicks)) {
            return new ArrayList<>();
        }
        
        // 获取美食ID列表
        List<Integer> foodIds = topClicks.stream()
                .map(vo -> {
                    // 根据美食名称查询美食ID
                    LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(Food::getFoodName, vo.getFoodName());
                    Food food = this.getOne(queryWrapper);
                    return food != null ? food.getFoodId() : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        
        // 根据ID列表查询美食信息
        List<Food> allFoods = this.listByIds(foodIds);
        
        // 过滤出用户收藏分类的美食
        return allFoods.stream()
                .filter(food -> categories.contains(food.getCategoryName()))
                .limit(10)
                .collect(Collectors.toList());
    }

    @Override
    public List<Food> like(FoodLikeParam foodLikeParam) {
        LambdaQueryWrapper<Food> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.like(Food::getFoodName,foodLikeParam.getFoodName());
        return this.list(lambdaQueryWrapper);
    }

    /**
     * 获取美食详情，并增加美食点击数
     *
     */
    @Override
    public FoodDetailsVo detail(FoodDetailParam foodDetailParam) {
        foodClicksService.likeAmount(foodDetailParam.getFoodId());
        return foodMapper.details(foodDetailParam.getFoodId());

    }
    /**
     * 获取炒菜美食分类
     */
    @Override
    public Page<Food> chaoCaiPage(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Food::getCategoryName,CHAO_CAI.getValue());
        return this.page(page,queryWrapper);
    }
    /**
     * 获取炖菜美食分类
     */
    @Override
    public Page<Food> dunCaiPage(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Food::getCategoryName,DUN_CAI.getValue());
        return this.page(page,queryWrapper);
    }

    @Override
    public Page<Food> shaoKaoPage(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Food::getCategoryName,SHAO_KAO.getValue());
        return this.page(page,queryWrapper);
    }

    @Override
    public Page<Food> zhengCaiPage(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Food::getCategoryName,ZHENG_CAI.getValue());
        return this.page(page,queryWrapper);
    }

    @Override
    public Page<Food> zhuShiPage(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Food::getCategoryName,ZHU_SHI.getValue());
        return this.page(page,queryWrapper);
    }

    @Override
    public Page<Food> xiaoChiPage(FoodPageParam foodPageParam) {
        Page<Food> page = new Page<>(foodPageParam.getPage(), foodPageParam.getSize());
        LambdaQueryWrapper<Food> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Food::getCategoryName,XIAO_CHI.getValue());
        return this.page(page,queryWrapper);
    }

    @Override
    public List<Food> favoriteFood(List<Integer> list) {
        return this.listByIds(list);
    }

    @Override
    public Long amount() {
        return this.count();
    }
}
